let Vue

class Store {
    constructor (options = {}) {
        const { state = {}, mutations = {}, getters = {}, actions = {} } = options
        this._vm = new Vue({
            data: {
                $$state: state
            }
        })
        this.mutations = mutations
        this.actions = actions
        this.getters = {}
        Object.keys(getters).forEach(key => {
            Object.defineProperty(this.getters, key, {
                get: () => getters[key](this.state)
            })
        })
        this.commit = this.commit.bind(this)
        this.dispatch = this.dispatch.bind(this)
    }

    get state () {
        return this._vm._data.$$state
    }

    commit (type, payload) {
        const mutation = this.mutations[type]
        mutation(this.state, payload)
    }

    dispatch (type, payload) {
        const action = this.actions[type]
        action(this, payload)
    }
}

function install (_Vue) {
    Vue = _Vue

    Vue.mixin({
        beforeCreate () {
            if (this.$options.store) {
                this.$store = this.$options.store
            } else if (this.$parent && this.$parent.$store) {
                this.$store = this.$parent.$store
            }
        }
    })
}

export default {
    Store,
    install
}
